/*
 * COMP6471 Project
 *  
 * This file is created by Yuan Tao (ewan.msn@gmail.com)
 * Licensed under GNU GPL v3
 * 
 * $Author: ewan.msn@gmail.com $
 * $Date: 2011-10-26 04:10:45 +0000 (Wed, 26 Oct 2011) $
 * $Rev: 42 $
 * $HeadURL: http://comp6471.googlecode.com/svn/Project3/src/UI/UIConsole.java $
 * 
 */
package UI;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.StringTokenizer;

import util.logger;

import kklib.Layout;

public class UIConsole implements UIController {

	@Override
	public int showGreetings() {
		System.out.println("Hi, wellcome to COMP6471 Project3. v0.1");
		System.out.println("Developed by Yuan Tao (ewan.msn@gmail.com)\n");
		System.out.println("The game files are under the root directoy of $ThisProgram\\input\\");
		System.out.println("There are already some sample txt files under $input directory.");
		System.out.println("Then press any key to begin...");
		
		try {
			InputStreamReader isr = new InputStreamReader(System.in);
			BufferedReader br = new BufferedReader(isr);
			
			br.readLine();
		} catch (IOException e) {
			logger.err("in.read: " + e.getMessage());
			return -1;
		}
		return 0;
	}
	
	/*
	 * +---+---+    						(first line)
       |       |    show cage formulas		(middle line)
       +   +---+    						(bottom line)
       |   |   |    show cage formulas
       +---+---+    						(last line)
	 */
	private void printOutGame(Layout layout) {
		System.out.println("Game Name: " + layout.gameName);
		
		// first line
		System.out.print("+");
		for (int i = 0; i < layout.gameSize; i++) {
			System.out.print("---+");
		}
		System.out.println("");
		
		for (int i = 0; i < layout.gameSize; i++) {
			int val = 0, data = 0, nextData = 0;
			
			// middle line
			System.out.print("|");
			for (int j = 0; j < layout.gameSize - 1; j++) {
				val = layout.rows.get(i * layout.gameSize + j).value;
				data = layout.rows.get(i * layout.gameSize + j).data;
				nextData = layout.rows.get(i * layout.gameSize + j + 1).data;
				
				System.out.print(" " + (val != 0 ? val : " ") + (data == nextData ? "  " : " |"));
			}
			val = layout.rows.get(i * layout.gameSize + layout.gameSize - 1).value;
			System.out.print(" " + (val != 0 ? val : " ") + " |");
			
			// show cage formulas
			System.out.print("\t");
			for (int j = 0; j <= layout.gameSize / 2; j++) {
				int index = i * (layout.gameSize / 2 + 1) + j;
				if (index < layout.txtFileFormulas.size()) {
					System.out.print("[" + layout.txtFileFormulas.get(index) + "] ");
				}
			}
			System.out.println("");
			
			// bottom line
			if (i != layout.gameSize - 1) {
				System.out.print("+");
				for (int j = 0; j < layout.gameSize; j++) {
					data = layout.rows.get(i * layout.gameSize + j).data;
					nextData = layout.rows.get((i + 1) * layout.gameSize + j).data;
					
					System.out.print(data == nextData ? "   +" : "---+");
				}
				System.out.println("");
			}
		}
		
		// last line
		System.out.print("+");
		for (int k = 0; k < layout.gameSize; k++) {
			System.out.print("---+");
		}
		System.out.println("");
	}
	
	private void printOutGames(ArrayList<Layout> layouts) {
		for (int i = 0; i < layouts.size(); i++) {
			printOutGame(layouts.get(i));
			System.out.println("");
		}
	}

	@Override
	public Layout showAllGamesAndChooseAGame(ArrayList<Layout> layouts) {
		// show all the games to user
		System.out.println("\n");
		printOutGames(layouts);
		
		String strSelection = "";
		// let user select a game
		for (int i = 0; i < layouts.size(); i++) {
			strSelection  += (i + 1) + ":" + layouts.get(i).gameName + " ";
		}
		System.out.println("Choose a game: " + strSelection + " OR exit");
		
		InputStreamReader isr = new InputStreamReader(System.in);
		BufferedReader br = new BufferedReader(isr);

		try {
			do {
				String line = br.readLine().trim();
				
				// if exit
				if (line.toLowerCase().compareToIgnoreCase("exit") == 0 ||
						line.toLowerCase().compareToIgnoreCase("quit") == 0) {
					return null;
				}
				
				// get the game NO.
				int no = 0;
				try {
					no = Integer.parseInt(line);
					
					if (no < 1 || no > layouts.size()) {
						System.out.println("Wrong game NO., please input again.");
						continue;
					}
				} catch (NumberFormatException e) {
					System.out.println("Wrong game NO., please input again.");
					continue;
				}

				return layouts.get(no - 1);
			} while (true);
		} catch (IOException e) {
			logger.err("readline: " + e.getMessage());
			return null;
		}
	}

	@Override
	public int getCellValues(Layout layout) {
		if (layout == null) {
			System.out.println("Fatal error!");
			logger.err("getCellValues. layout == null");
			return 1;
		}
		
		// first, print out the current layout status.
		System.out.println("");
		printOutGame(layout);
		System.out.println("Please input the values of cells, e.g. a1=2 OR a1=2 b3=3 a2=4 OR exit");
		
		// get input values of cells
		// parse the values from string like "a1:2" or "a1:2 b3:3 a2:4"
		InputStreamReader isr = new InputStreamReader(System.in);
		BufferedReader br = new BufferedReader(isr);
		String line;
		
		try {
			System.out.flush();
			line = br.readLine().trim().toUpperCase();
		} catch (IOException e) {
			logger.err(e.getMessage());
			return -1;
		}
		
		StringTokenizer st = new StringTokenizer(line); 
		int cnt = st.countTokens();
		if (cnt < 1) {
			return -1;		// empty line
		}
		
		while (cnt-- > 0) {
			String token = st.nextToken();
			
			// check if exit
			if (token.compareToIgnoreCase("exit") == 0 ||
					token.compareToIgnoreCase("quit") == 0) {
				return 1;
			}
			
			// check correction of  input value
			if (token.length() != 4) {				
				return -1;		// input error. Game size must be < 10
			}
			
			char ch = token.charAt(0);
			
			if (ch < 'A' || ch > 'A' + layout.gameSize - 1) {
				return -1;		// input error
			}
			ch = token.charAt(1);
			if (ch < '1' || ch > '1' + layout.gameSize - 1) {
				return -1;		// input error
			}
			
			int val = 0;
			
			try {
				val = Integer.parseInt(token.substring(3));
			} catch (NumberFormatException e) {
				return -1;
			}			
			
			// set the value to cell
			if (layout.setCellValue(token.substring(0, 2), val) != 0) {
				System.out.println("Fatal error!");
				logger.err("setCellValue.");
				return 1;
			}				
		}
		  
		return 0;
	}

	@Override
	public void showMessage(String msg) {
		System.out.println("\n");
		System.out.println(msg);
		logger.info(msg);
	}

	@Override
	public boolean ifPlayAgain() {
		System.out.println("\nPlay it again? 'y' OR any key to exit");
		
		InputStreamReader isr = new InputStreamReader(System.in);
		BufferedReader br = new BufferedReader(isr);
		try {
			String line = br.readLine().trim().toLowerCase();
			
			if (line.compareToIgnoreCase("yes") == 0 ||
					line.compareToIgnoreCase("y") == 0) {
				return true;
			}
			
		} catch (IOException e) {
			logger.err("readline: " + e.getMessage());
			return false;
		}
		return false;
	}

	@Override
	public void showLayout(Layout layout) {
		printOutGame(layout);		
	}

}
